#include "serialport.h"

#include <QDebug>


void  NumToHex(quint16 cIn, unsigned char szOut[2])
{
    if ((cIn & 0xFF)<10)
    {
        szOut[0] = (cIn & 0x0F) + '0';
    } else {
        szOut[0] = (cIn & 0x0F)-10+'A';

    }

    if(((cIn>>4) & 0x0F)<10)
    {
        szOut[1] = ((cIn>>4) & 0x0F) + '0';
    } else {
        szOut[1] = ((cIn>>4) & 0x0F) - 10 + 'A';
    }
}

void  HexToNum(unsigned char szIn[2], quint16 *cOut, int num)
{
    *cOut = 0;
    if (num > 0)
    {
        if (szIn[1] >= 'A')
        {
            *cOut = *cOut + (szIn[1] - 'A' + 10) % 16 * 16;
        } else if (szIn[1] >= '0') {
            *cOut = *cOut + (szIn[1] - '0') % 16 * 16;
        }
    }

    if (szIn[0] >= 'A')
    {
        *cOut = *cOut + (szIn[0] - 'A' + 10) / 16 * 10 + (szIn[0] - 'A' + 10) % 16;
    } else if (szIn[0] >= '0')
    {
        *cOut = *cOut + (szIn[0] - '0') / 16 * 10 + (szIn[0] - '0') % 16;
    }
}

SerialPort::SerialPort(int type, QObject *parent) :
    QObject(parent), serialType(type)
{
    init();

}

SerialPort::~SerialPort()
{
    closeThread();
}

/*******************************************
  功能：初始化函数，初始化一些必要的参数
  参数：
  返回值：
  ******************************************/
void SerialPort::init()
{
    portIsOpen = false;
    sendIsAscii = false;

    setDefaultPortSetting();
    qextSerialThread = new QextSerialThread(mPort, this);

    connect(qextSerialThread, SIGNAL(receBytes(QByteArray)), this, SLOT(receBytes(QByteArray)));
    connect(this, SIGNAL(sentBytes(QByteArray)), qextSerialThread, SLOT(sentByteSlot(QByteArray)));

}

/*******************************************
  功能：发送命令到LCD屏
  参数：
  返回值：
  ******************************************/
inline quint8 SerialPort::sendLcdCmd(const LcdSendStruct &lcdSendStruct)
{

    LcdSendStruct sendStruct = lcdSendStruct;
    QByteArray sendData;
    QDataStream sendStream(&sendData,QIODevice::WriteOnly);
    sendStream.setVersion(QDataStream::Qt_4_6);

    quint16 length;
    length = 5 + lcdSendStruct.valueList.count();
    NumToHex(length, sendStruct.length);
    countCheckSum(sendStruct);

    sendStream << quint16(0xFA4D);
    sendStream << sendStruct.length[1];
    sendStream << sendStruct.length[0];

    sendStream << sendStruct.sendMode;
    sendStream << sendStruct.address[1];
    sendStream << sendStruct.address[0];

    sendStream << sendStruct.cmd;
    for(int i = 0; i < sendStruct.valueList.count(); i++)
    {
        sendStream << sendStruct.valueList.at(i);
    }

    sendStream << sendStruct.checkSum;
    sendStream << sendStruct.inCheckSum;
    sendStream << quint16(0xFA45);

    this->write(sendData);
    return sendData.size();
}


/*******************************************
  功能：计算出checksum和inchecksum
  参数：
  返回值：
  ******************************************/
inline void SerialPort::countCheckSum(LcdSendStruct &lcdSendStruct)
{
    quint8 checkSum;
    quint8 cmd1 = lcdSendStruct.cmd & 0xFF;
    quint8 cmd2 = (lcdSendStruct.cmd >> 8) & 0xFF;

    checkSum = lcdSendStruct.length[0] + lcdSendStruct.length[1] + lcdSendStruct.sendMode + lcdSendStruct.address[0] + lcdSendStruct.address[1] + cmd1 + cmd2;
    for(int i = 0; i < lcdSendStruct.valueList.count(); i++)
    {
        checkSum += lcdSendStruct.valueList.at(i);
    }
    lcdSendStruct.checkSum = checkSum;
    lcdSendStruct.inCheckSum = quint8(0xFF) - checkSum;
}

/*******************************************
  功能：处理感光板的数据
  参数：
  返回值：多余的数据
  ******************************************/
QByteArray SerialPort::processSensorData(const QByteArray& bytes)
{

    int processCount = 0;
    QByteArray receBytes = bytes;
    QByteArray logBytes = bytes.toHex();
    int DataSize = mReceBytes.size();
    QDataStream receStream(&mReceBytes,QIODevice::ReadOnly);
    receStream.setVersion(QDataStream::Qt_4_6);

    quint8 data8;

    quint16 header16;
    quint16 data16;
    quint8 eof;

    bool receDataIsRight = false;
    while(!receStream.atEnd() && processCount < mReceBytes.size())
    {
        //根据类型的不同分为两种解析情况：一种是感光器的解析，一种是LCD的解析
        //串口类型（0：接收环境光度感应；1，LCD显示屏控制）
        receStream >> data8;
        if (data8 != 0)
        {
            receStream.skipRawData(-1);
            receStream >> header16;
            if (header16 == quint16(0x55A7))
            {
                receStream >> data16;
                receStream >> eof;
                if (eof != quint8(0xAA))
                {
                    receStream.skipRawData(-4);
                    processCount++;
                    if (DataSize - processCount < SENSOR_REPLY_DATA_MAXIMUM)
                    {
                        break;
                    }
                    continue;
                } else {
                    receDataIsRight = true;
                    emit receSensorData(data16);
                    if (g_stDebugConfig.isDebugSerialPort)
                    {
                        qDebug() << "processSensorData, SensorData:" << data16;
                    }
                }
                processCount = processCount + 5;
                if (DataSize - processCount < SENSOR_REPLY_DATA_MAXIMUM)
                {
                    break;
                }
            } else {               
                receStream.skipRawData(-1);
                processCount++;
                if (DataSize - processCount < SENSOR_REPLY_DATA_MAXIMUM)
                {
                    break;
                }
            }
        } else {
            processCount++;
        }
    }

    if (!receDataIsRight)
    {
        //如果串口收到数据,且不正确,那写入日志文件中
        QString logMsg;
        //#ifdef IS_PRINT_ERR_DATA_TO_LOG
        if (g_stDebugConfig.isDebugSerialPort)
        {
            for(int i = 0; i < logBytes.count(); i++)
            {
                if (i > 200)
                    break;
                if (i % 2 == 0)
                    logMsg += "0x";

                logMsg += logBytes[i];
                if (i % 2 != 0)
                    logMsg += " ";
            }
            logger()->warn(tr("Rece sensor data from %1,but data is err, data size is:%2, remove size is %3\n"
                              "Rece data is: %4\n").arg(mPort).arg(DataSize).arg(processCount).arg(logMsg));
        } else {
            logger()->warn(tr("Rece sensor data from %1,but data is err, data size is:%2, remove size is %3\n").arg(mPort).arg(DataSize).arg(processCount));
        }
    }

    receBytes.remove(0, processCount);
//    qDebug() << "receDataIsRight:" << receDataIsRight << "receBytes" << receBytes.size() << processCount;

    return receBytes;
}


/*******************************************
  功能：处理LCD回复的数据
  参数：
  返回值：多余的数据
  ******************************************/
QByteArray SerialPort::processLcdReply(const QByteArray& bytes)
{
    QByteArray receBytes = bytes;
    //将每一次的数据存进成员变量mReceBytes中
//    mReceBytes.append(receBytes);

    QDataStream receStream(&mReceBytes,QIODevice::ReadOnly);
    receStream.setVersion(QDataStream::Qt_4_6);


    //用来记录处理了多少数据，如果有下个数据包的数据，那么返回存放到下次一起处理
    int processCount = 0;
    quint16 header16;
    quint16 packEnd16;
    LcdReplayStruct lcdReply;
    LcdReplay reply;
    quint16 i16Value;
    int receDataSize = receBytes.size();
    QByteArray logBytes = bytes.toHex();

    unsigned char   length[2];
    unsigned char   address[2];
    unsigned char   cValue[2];
    unsigned char   cOVlaue;
    qint16 checkSum = 0;

    bool receDataIsRight = false;

    while (!receStream.atEnd())
    {
        checkSum = 0;
        receStream >> header16;
        if (header16 == quint16(0xFA53))
        {
            receStream >> length[1];
            receStream >> length[0];
            checkSum = checkSum + length[0] + length[1];

            receStream >> lcdReply.sendMode;
            receStream >> address[1];
            receStream >> address[0];
            receStream >> lcdReply.cmd;
            checkSum = checkSum + lcdReply.sendMode + address[0] + address[1] +
                    ((lcdReply.cmd >> 8) & 0xFF) + (lcdReply.cmd & 0xFF);

            HexToNum(length, &lcdReply.length, 2);
            HexToNum(address, &lcdReply.address, 2);

            if (lcdReply.length == 9)
            {
                if (lcdReply.cmd == quint16(0x00C9))
                {
                    receStream >> lcdReply.videoStatus;
                    checkSum = checkSum + ((lcdReply.videoStatus >> 24) & 0x00FF) +
                            ((lcdReply.videoStatus >> 16) & 0x00FF) + ((lcdReply.videoStatus >> 8) & 0x00FF) +
                            (lcdReply.videoStatus & 0x00FF);
                } else {
                    receStream >> cValue[1] >> cValue[0];
                    checkSum = checkSum + cValue[0] + cValue[1];
                    HexToNum(cValue, &lcdReply.value1, 2);

                    receStream >> cValue[1] >> cValue[0];
                    checkSum = checkSum + cValue[0] + cValue[1];
                    HexToNum(cValue, &lcdReply.value2, 2);
                    lcdReply.valueCmd = 0xFF;
                }
            } else if (lcdReply.length == 8){
                unsigned char cValue[2];
                receStream >> lcdReply.valueCmd;
                receStream >> cValue[1] >> cValue[0];
                HexToNum(cValue, &lcdReply.value1, 2);
                checkSum = checkSum + lcdReply.valueCmd + cValue[0] + cValue[1];

            } else if (lcdReply.length == 7)
            {
                receStream >> cOVlaue;
                checkSum = checkSum + cOVlaue;

                HexToNum(&cOVlaue, &i16Value, -1);
                lcdReply.blStatus = i16Value;

                receStream >> cOVlaue;
                checkSum = checkSum + cOVlaue;

                HexToNum(&cOVlaue, &i16Value, -1);
                lcdReply.blStatus = i16Value;

                lcdReply.valueCmd = 0xFE;
            } else if (lcdReply.length == 6)
            {
                receStream >> lcdReply.valueCmd;
                checkSum = checkSum + lcdReply.valueCmd;
            } else {
                receStream.skipRawData(-8);

                processCount += 1;
                if (receBytes.size() - processCount < LCD_REPLY_DATA_MINIMUM)
                {
                    break;
                }
                continue;
            }

            receStream >> lcdReply.checkSum;
            receStream >> lcdReply.inCheckSum;

            receStream >> packEnd16;

            if (packEnd16 != quint16(0xFA45))
            {
                receStream.skipRawData(-1 * (8 + lcdReply.length-1));
                processCount += 1;
                if (receBytes.size() - processCount < LCD_REPLY_DATA_MINIMUM)
                {
                    break;
                }
                continue;
            }

            if ((lcdReply.checkSum + lcdReply.inCheckSum == 0xFF) && lcdReply.checkSum == quint8(checkSum & 0xFF))
            {
                if (lcdReply.cmd == quint16(0x00E0))
                {
                    switch (lcdReply.valueCmd)
                    {
                    case quint8(0x2B):
                    case quint8(0x2D):
                        reply.cmd = lcdReply.valueCmd;
                        reply.panelID = lcdReply.address;
                        reply.brightness = lcdReply.value1;
                        emit lcdReplyBrightness(reply);
                        receDataIsRight = true;
                        break;
                    case quint8(0x52):
                        reply.cmd = lcdReply.valueCmd;
                        reply.panelID = lcdReply.address;
                        reply.brightness = lcdReply.value1;
                        emit lcdReplyReset(reply);
                        receDataIsRight = true;
                        break;
                    case quint8(0xFF):
                        reply.cmd = lcdReply.valueCmd;
                        reply.panelID = lcdReply.address;
                        reply.brightness = lcdReply.value1;
                        emit lcdReplyBrightness(reply);                        
                        receDataIsRight = true;
                        break;
                    default:
                        break;
                    }

                } else if (lcdReply.cmd == quint16(0x00C9))
                {
                    reply.cmd = lcdReply.valueCmd;
                    reply.panelID = lcdReply.address;
                    reply.videoStatus = (quint32)lcdReply.videoStatus;

                    emit lcdReplyVideoStatu(reply);
                    receDataIsRight = true;
                } else if (lcdReply.cmd == quint16(0x00E1))
                {
                    reply.cmd = lcdReply.valueCmd;
                    reply.panelID = lcdReply.address;
                    reply.blStatus = lcdReply.blStatus;

                    emit lcdReplyBLStatus(reply);
                    receDataIsRight = true;
                } else {
                    receStream.skipRawData(-1 * (8 + lcdReply.length-1));
                    processCount += 1;
                    if (receBytes.size() - processCount < LCD_REPLY_DATA_MINIMUM)
                    {
                        break;
                    }
                    continue;
                }
                processCount = processCount + 8 + lcdReply.length;
                if (receBytes.size() - processCount < LCD_REPLY_DATA_MINIMUM)
                {
                    break;
                }

            }
        } else {
            receStream.skipRawData(-1);
            processCount += 1;
            if (receBytes.size() - processCount < LCD_REPLY_DATA_MINIMUM)
            {
                break;
            }
        }
    }

    if (!receDataIsRight)
    {
        if (receDataSize > LCD_REPLY_DATA_MAXIMUM)
        {
            if (receDataSize - processCount < LCD_REPLY_DATA_MAXIMUM)
            {
                processCount = receBytes.size() - LCD_REPLY_DATA_MAXIMUM;
            }
        } else {
            processCount = 0;
        }

        //如果串口收到数据,且不正确,那写入日志文件中
        QString logMsg;
        //#ifdef IS_PRINT_ERR_DATA_TO_LOG
        if (g_stDebugConfig.isDebugSerialPort)
        {
            for(int i = 0; i < logBytes.count(); i++)
            {
                if (i > 200)
                    break;
                if (i % 2 == 0)
                    logMsg += "0x";
                logMsg += logBytes[i];
                if (i % 2 != 0)
                    logMsg += " ";
            }
            logger()->warn(tr("Rece lcd answer data from %1,but data is err, data size is:%2, remove size is %3\n"
                              "Rece data is: %4\n").arg(mPort).arg(receDataSize).arg(processCount).arg(logMsg));
        } else {
            logger()->warn(tr("Rece sync data from %1,but data is err, data size is:%2, remove size is %3\n").arg(mPort).arg(receDataSize).arg(processCount));
        }
    }

    receBytes.remove(0, processCount);
    return receBytes;
}

//处理SLCD间通信的协议数据
QByteArray SerialPort::processSynchCommand(const QByteArray& bytes)
{
    SynchCommand syncCommand;
    int processCount = 0;
    QByteArray receBytes = bytes;
//    mReceBytes.append(receBytes);
    QByteArray logBytes = bytes.toHex();
    int DataSize = mReceBytes.size();
    QDataStream receStream(&mReceBytes,QIODevice::ReadOnly);
    receStream.setVersion(QDataStream::Qt_4_6);

    qint8 header8;
    qint16 checkSum;

    bool receDataIsRight = false;


    while(!receStream.atEnd())
    {
        //根据类型的不同分为两种解析情况：一种是感光器的解析，一种是LCD的解析
        //串口类型（0：接收环境光度感应；1，LCD显示屏控制）
        receStream >> header8;

        if (header8 != 0)
        {
            if (header8 == qint8(0xFF))
            {
                syncCommand.stx = header8;
                receStream >> syncCommand.enquiryNum >> syncCommand.typeDev;
                receStream >> syncCommand.year >> syncCommand.month >> syncCommand.day;
                receStream >> syncCommand.hour >> syncCommand.minute >> syncCommand.second;
                receStream >> syncCommand.brightness;
                receStream >> syncCommand.reserved >> syncCommand.ext >> syncCommand.checkSum;

                if (syncCommand.ext != qint8(0xFE))
                {
//                    qDebug() << "syncCommand.ext != qint8(0xFE)";
                    receStream.skipRawData(-1*(SYNC_REPLY_DATA_MAXIMUM-1));
                    processCount=processCount+1;
                    if (DataSize - processCount < SYNC_REPLY_DATA_MAXIMUM)
                    {
                        break;
                    }
                    continue;
//                    receStream.skipRawData(-21);
                } else {
                    checkSum = syncCommand.enquiryNum + syncCommand.typeDev + syncCommand.year +
                            syncCommand.month + syncCommand.day + syncCommand.hour + syncCommand.minute +
                            syncCommand.second + syncCommand.brightness;
                    if (checkSum == syncCommand.checkSum)
                    {
                        if (g_stDebugConfig.isDebugSerialPort)
                        {
                            qDebug() << "processSynchCommand, receSyncCommand" << syncCommand.brightness;
                        }
                        emit receSyncCommand(syncCommand);
                        receDataIsRight = true;
                    } else {
                        receStream.skipRawData(-1*(SYNC_REPLY_DATA_MAXIMUM-1));
                        processCount=processCount+1;
                        if (DataSize - processCount < SYNC_REPLY_DATA_MAXIMUM)
                        {
                            break;
                        }
                        continue;
                    }
                    processCount = processCount + SYNC_REPLY_DATA_MAXIMUM;
                    if (DataSize - processCount < SYNC_REPLY_DATA_MAXIMUM)
                    {
                        break;
                    }
                }
            } else {                
                processCount++;
                if (DataSize - processCount < SYNC_REPLY_DATA_MAXIMUM)
                {
                    break;
                }
            }
        } else {
            processCount++;
        }
    }

    if (!receDataIsRight)
    {
        //如果串口收到数据,且不正确,那写入日志文件中
        QString logMsg;
//#ifdef IS_PRINT_ERR_DATA_TO_LOG
        if (g_stDebugConfig.isDebugSerialPort)
        {
            for(int i = 0; i < logBytes.count(); i++)
            {
                if (i > 200)
                    break;
                if (i % 2 == 0)
                    logMsg += "0x";
                logMsg += logBytes[i];
                if (i % 2 != 0)
                    logMsg += " ";
            }
            logger()->warn(tr("Rece sync data from %1,but data is err, data size is:%2, remove size is %3\n"
                              "Rece data is: %4\n").arg(mPort).arg(DataSize).arg(processCount).arg(logMsg));
        } else {
            logger()->warn(tr("Rece sync data from %1,but data is err, data size is:%2, remove size is %3\n").arg(mPort).arg(DataSize).arg(processCount));
        }
    }

    receBytes.remove(0, processCount);

    return receBytes;
}

/*******************************************
  功能：打开串口，打开后串口正式可以接收和发送数据
  参数：openMode,打开方式，跟打开文件方式一样，可读可写等
  返回值：
  ******************************************/
bool SerialPort::openSeriPort(QIODevice::OpenMode openMode)
{
    qextSerialThread->setPortSettings(mPortSettings);
    qextSerialThread->setReadTime(mTimeSize);

    //每打开一个串口就开启一个串口数据读取线程qextSerialThread
    if (qextSerialThread->isRunning())
    {
        if (qextSerialThread->openSeriPort(openMode))
        {
             portIsOpen = true;
        }
        return portIsOpen;
    } else {
        qextSerialThread->start();
        //等待线程的运行，50ms的等待时间
        usleep(1000 * 50);
//         portIsOpen = true;
         portIsOpen = qextSerialThread->isOpen();
        return portIsOpen;
    }
    return false;
}

/*******************************************
  功能：关闭串口
  参数：
  返回值：
  ******************************************/
void SerialPort::cloesSeriPort()
{
     portIsOpen = false;
    qextSerialThread->closeSeriPort();
}

/*******************************************
  功能：设置LCD ID列表
  参数：list,LCD ID列表
  返回值：
  ******************************************/
void SerialPort::setPanelInfoIDList(const QList<PanelInfoStruct> infoList)
{
    m_panelInfoList = infoList;
}


/*******************************************
  功能：是否已经打开
  参数：
  返回值：返回是否打开状态
  ******************************************/
bool SerialPort::isOpen() const
{
    return qextSerialThread->isOpen();
}

/*******************************************
  功能：是否可读
  参数：
  返回值：返回是否可读状态
  ******************************************/
bool SerialPort::isReadable() const
{
    return qextSerialThread->isReadable();
}

/*******************************************
  功能：是否可写
  参数：
  返回值：返回是否可写状态
  ******************************************/
bool SerialPort::isWritable() const
{
    return qextSerialThread->isWritable();
}

/*******************************************
  功能：设置默认串口基本参数口
  参数：
  返回值：
  ******************************************/
void SerialPort::setDefaultPortSetting()
{
    mPortSettings.BaudRate = BAUD9600;
    mPortSettings.DataBits = DATA_8;
    mPortSettings.Parity = PAR_NONE;
    mPortSettings.StopBits = STOP_1;
    mPortSettings.FlowControl = FLOW_OFF;
    mPortSettings.Timeout_Millisec = 10;
    mTimeSize = 500;
}

/*******************************************
  功能：得到已经从串口中读取到的数据的字节数
  参数：
  返回值：已经从串口中读取到的数据的字节数
  ******************************************/
int SerialPort::bytesAvailable()
{
    return mReceBytes.size();
}

/*******************************************
  功能：将串口收到的数据全部一次性全部读取出来
  参数：
  返回值：串口收到的数据
  ******************************************/
QByteArray SerialPort::readAll()
{
    QByteArray receByte = mReceBytes;
    mReceBytes.clear();
    mReceBytes.resize(0);

    return receByte;
}

/*******************************************
  功能：写函数，将数据写进串口，即从串口发送出去
  参数：sendBytes,要发送的数据
  返回值：
  ******************************************/
inline int SerialPort::write(QByteArray sendBytes)
{
    emit sentBytes(sendBytes);
    return sendBytes.size();
}

/*******************************************
  功能：设置端口
  参数：port,端口号名称
  返回值：
  ******************************************/
void SerialPort::setPort(const QString& port)
{
    mPort = port;
    qextSerialThread->setPort(mPort);
}

/*******************************************
  功能：设置串口读取时间
  参数：timeSize,读取时间值
  返回值：
  ******************************************/
void SerialPort::setReadTime(int timeSize)
{
    mTimeSize = timeSize;
}

/*******************************************
  功能：设置 串口波特率
  参数：baudRateType,串口波特率
  返回值：
  ******************************************/
void SerialPort::setBaudRate(BaudRateType baudRateType)
{
    mPortSettings.BaudRate = baudRateType;
    if (portIsOpen)
    {
        qextSerialThread->setBaudRate(baudRateType);
    }

}

/*******************************************
  功能：设置 串口数据位
  参数：dataBitsType,串口数据位
  返回值：
  ******************************************/
void SerialPort::setDataBits(DataBitsType dataBits)
{
    mPortSettings.DataBits = dataBits;

    if (portIsOpen)
    {
        qextSerialThread->setDataBits(dataBits);
    }
}

/*******************************************
  功能：设置 串口奇偶验证位
  参数：parityType,串口奇偶验证位
  返回值：
  ******************************************/
void SerialPort::setParity(ParityType  parityType)
{
    mPortSettings.Parity = parityType;

    if (portIsOpen)
    {
        qextSerialThread->setParity(parityType);
    }
}

/*******************************************
  功能：设置 串口停止位
  参数：stopBits,串口停止位
  返回值：
  ******************************************/
void SerialPort::setStopBits(StopBitsType stopBits)
{
    mPortSettings.StopBits = stopBits;

    if (portIsOpen)
    {
        qextSerialThread->setStopBits(stopBits);
    }
}

/*******************************************
  功能：设置 串口数据流控件
  参数：flowType,串口数据流控件
  返回值：
  ******************************************/
void SerialPort::setFlowControl(FlowType flowCtl)
{
    mPortSettings.FlowControl = flowCtl;

    if (portIsOpen)
    {
        qextSerialThread->setFlowControl(flowCtl);
    }
}

/*******************************************
  功能：设置 串口读取时间
  参数：time,串口读取时间
  返回值：
  ******************************************/
void SerialPort::setTimeout(long time)
{
    mPortSettings.Timeout_Millisec = time;
}

/*******************************************
  功能：控制DTR,低位接收形式，置位的时候会有一定的时间间隔
  参数：
  返回值：
  ******************************************/
void SerialPort::setDtr(bool set)
{
    qextSerialThread->setDtr(set);
}

/*******************************************
  功能：控制RTS，高位发送命令形式，低位接收形式，置位的时候会有一定的时间间隔
  参数：
  返回值：
  ******************************************/
void SerialPort::setRts(bool set)
{
    qextSerialThread->setRts(set);
}

/*******************************************
  功能：设置 通过串口结构体直接一次性设置全部串口基本设置
  参数：portSettings,串口结构体
  返回值：
  ******************************************/
void SerialPort::setPortSettings(PortSettings portSettings)
{
    mPortSettings = portSettings;
}

/*******************************************
  功能：线程关闭
  参数：
  返回值：
  ******************************************/
void SerialPort::closeThread()
{
    if (qextSerialThread->isRunning())
    {
        qextSerialThread->closeSeriPort();
        qextSerialThread->quit();
        qextSerialThread->wait(100);
    }

}

/*******************************************
  功能：面板选择
  参数：panleID,面板ID号
  返回值：
  ******************************************/
inline void SerialPort::selectPanel(qint16 panelID)
{
    QByteArray sendData;
    QDataStream sendStream(&sendData,QIODevice::WriteOnly);
    sendStream.setVersion(QDataStream::Qt_4_6);

    //拆分为10位和个位，然后转化为字符型数字
//    quint8 tenBrightness = panelID / 10 + 0x30;
//    quint8 unitBrightness = panelID % 10 + 0x30;

    unsigned char hexPlanID[2] = {0};
    NumToHex(panelID, hexPlanID);

    //转化为字符型的命令
    sendStream << quint8(0xe1);
    sendStream << quint8(0xd5);

//    if (sendIsAscii)
//    {
//        sendStream << tenBrightness;
//        sendStream << unitBrightness;
//    } else {
//        sendStream << panelID;
//    }


    sendStream << hexPlanID[0];
    sendStream << hexPlanID[1];

    emit sentBytes(sendData);
}

/*******************************************
  功能：亮度控制，广播方式
  参数：brightness,要发送的命令
  返回值：
  ******************************************/
void SerialPort::bcastCtlbrightness(qint16 brightness)
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD6);
    lcdCmd.cmd = quint16(0x00E0);
    NumToHex(0, lcdCmd.address);

//    brightness = brightness;
    if (brightness > BACKLIGHTLIMMIT)
    {
        brightness = BACKLIGHTLIMMIT;
    }

    unsigned char value[2];
    NumToHex(brightness, value);
    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(value[1]);
    lcdCmd.valueList.append(value[0]);

//    if (g_stDebugConfig.isDebugSerialPort)
//    {
//        qDebug() << "bcastCtlbrightness ====>" << "brightness:" << brightness;
//    }
    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：背光亮度设置，对单个
  参数：
  返回值：
  ******************************************/
void SerialPort::ctlBrightness(qint16 panelID, qint16 brightness)
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD5);
    lcdCmd.cmd = quint16(0x00E0);
    NumToHex(panelID, lcdCmd.address);

//    brightness = brightness + 1;
    if (brightness > BACKLIGHTLIMMIT)
    {
        brightness = BACKLIGHTLIMMIT;
    }

    unsigned char value[2];
    NumToHex(brightness, value);
    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(value[1]);
    lcdCmd.valueList.append(value[0]);

    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：广播 increment bcaklight
  参数：
  返回值：
  ******************************************/
void SerialPort::bcastIncrementBL()
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD6);
    lcdCmd.cmd = quint16(0x00E0);
    NumToHex(0, lcdCmd.address);
    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(0x2B);

    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：increment bcaklight
  参数：
  返回值：
  ******************************************/
 void SerialPort::incrementBL(qint16 panelID)
 {
     LcdSendStruct lcdCmd;
     lcdCmd.sendMode = quint8(0xD5);
     lcdCmd.cmd = quint16(0x00E0);
     NumToHex(panelID, lcdCmd.address);
     lcdCmd.valueList.clear();
     lcdCmd.valueList.append(0x2B);

     this->sendLcdCmd(lcdCmd);
 }

 /*******************************************
   功能：广播 decrement backlight
   参数：
   返回值：
   ******************************************/
void SerialPort::bcastDecrementBL()
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD6);
    lcdCmd.cmd = quint16(0x00E0);
    NumToHex(0, lcdCmd.address);
    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(0x2D);

    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：指定LCD屏进行decrement backlight
  参数：
  返回值：
  ******************************************/
void SerialPort::decrementBL(qint16 panelID)
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD5);
    lcdCmd.cmd = quint16(0x00E0);
    NumToHex(panelID, lcdCmd.address);
    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(0x2D);

    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：广播 设置原始设置
  参数：
  返回值：
  ******************************************/
void SerialPort::bcastResetBL()
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD6);
    lcdCmd.cmd = quint16(0x00E0);
    NumToHex(0, lcdCmd.address);

    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(0x52);

    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：指定LCD屏设置原始设置
  参数：
  返回值：
  ******************************************/
void SerialPort::resetBL(qint16 panleID)
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD5);
    lcdCmd.cmd = quint16(0x00E0);
    NumToHex(panleID, lcdCmd.address);
    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(0x52);

    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：广播 背景灯控制
  参数：cmd,要发送的命令
  返回值：
  ******************************************/
void SerialPort::bcastCtlBLStatu(quint8 cmd)
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD6);
    lcdCmd.cmd = quint16(0x00E1);
    NumToHex(0, lcdCmd.address);

    unsigned char value;
    value = cmd;
//    NumToHex(cmd, &value);
//    lcdCmd.valueList.append(value);
    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(value);

    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：指定屏进行 背景灯控制
  参数：cmd,要发送的命令
  返回值：
  ******************************************/
void SerialPort::ctlBLStatu(qint16 panelID, quint8 cmd)
{
    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD5);
    lcdCmd.cmd = quint16(0x00E1);
    NumToHex(panelID, lcdCmd.address);

    unsigned char value;
//    NumToHex(cmd, &value);
    value = cmd;
//    lcdCmd.valueList.append(value);
    lcdCmd.valueList.clear();
    lcdCmd.valueList.append(value);
    this->sendLcdCmd(lcdCmd);
}

/*******************************************
  功能：视频状态查询
  参数：cmd,要发送的命令
  返回值：
  ******************************************/
quint8 SerialPort::queryVideoStatus(qint16 panelID)
{

    LcdSendStruct lcdCmd;
    lcdCmd.sendMode = quint8(0xD5);
    lcdCmd.cmd = quint16(0x00C9);
    NumToHex(panelID, lcdCmd.address);

    quint8 size = this->sendLcdCmd(lcdCmd);
    return size;
}

/*******************************************
  功能：设置是否发送的为ascii码值
  参数：flag,是否发送的标志
  返回值：
  ******************************************/
void SerialPort::setSendIsAscii(const bool flag)
{
    sendIsAscii = flag;
}

/*******************************************
  功能：串口收到数据，然后将这些数据存贮在一个成员变量mReceBytes中,
          根据收到的数据进行相应的处理
  参数：receBytes,收到的数据
  返回值：
  ******************************************/
void SerialPort::receBytes(QByteArray receBytes)
{

//    int DataSize = mReceBytes.size();
//    QDataStream receStream(&mReceBytes,QIODevice::ReadOnly);
//    receStream.setVersion(QDataStream::Qt_4_6);

//    quint8 header8;
//    quint8 data8;

//    quint16 header16;
//    quint16 data16;
//    quint8 eof;
//    QStringList list1;

//    int dataCount = 0;
//    int count= 0;
//    bool isZero = false;
//    while(!receStream.atEnd())
//    {
//        receStream >> data8;

//        if (data8 != 0 || (isZero == true && dataCount < 5))
//        {
//            isZero = true;
//            QString str = QString::number(data8, 16);
//            if (str.count() > 2)
//            {
//                str = str.remove(0, str.count()-2);
//            }
//            list1 << str;
//            dataCount++;
//        } else if (dataCount >= 5)
//        {
//            dataCount = 0;
//            isZero = false;
//        }
//    }
//    receStream.skipRawData(-1 * DataSize);

    //将每一次的数据存进成员变量mReceBytes中
    mReceBytes.append(receBytes);

    QByteArray bytes;

    if (serialType == 0)
    {
        if (mReceBytes.size() >= SENSOR_REPLY_DATA_MAXIMUM)
        {

//            if (g_stDebugConfig.isDebugSerialPort)
//            {
//                qDebug() << "processSensorData, ReceBytes=============>" << receBytes.size();
//            }

            bytes = processSensorData(mReceBytes);
            this->readAll();
            mReceBytes = bytes;
        }
    } else if (serialType == 1){
        if (mReceBytes.size() >= LCD_REPLY_DATA_MINIMUM)
        {
            if (g_stDebugConfig.isDebugSerialPort)
            {
                qDebug() << "processLcdReply, ReceBytes=============>" << receBytes.size();
            }

            bytes = processLcdReply(mReceBytes);
            this->readAll();
            mReceBytes = bytes;
        }
    } else {
        if (mReceBytes.size() >= SYNC_REPLY_DATA_MAXIMUM)
        {
            if (g_stDebugConfig.isDebugSerialPort)
            {
                qDebug() << "processSynchCommand, ReceBytes=============>" << receBytes.size();
            }

            bytes = processSynchCommand(mReceBytes);
            this->readAll();
            mReceBytes = bytes;
        }
    }

}


/*******************************************
  功能：发送同步数据，主要同步时间和环境亮度
  参数：
  返回值：
  ******************************************/
void SerialPort::sendSynchCommand(const SynchCommand& synCommand)
{

    QByteArray sendData;
    int writeSize;

    QDataStream sendStream(&sendData,QIODevice::WriteOnly);
    sendStream.setVersion(QDataStream::Qt_4_6);

    sendStream << synCommand.stx << synCommand.enquiryNum << synCommand.typeDev;
    sendStream << synCommand.year << synCommand.month << synCommand.day;
    sendStream << synCommand.hour << synCommand.minute << synCommand.second;
    sendStream << synCommand.brightness << synCommand.reserved << synCommand.ext << synCommand.checkSum;

    writeSize = this->write(sendData);
//    emit sentBytes(sendData);
}

/*******************************************
  功能：发送数据
  参数：sendType,发送数据的类型; data,将要发送的数据;
  返回值：
  ******************************************/
void SerialPort::sendData(int sendType, QByteArray data)
{

        QByteArray sendData;
        QDataStream sendStream(&sendData,QIODevice::WriteOnly);
        sendStream.setVersion(QDataStream::Qt_4_6);

        qint16 header = qint16(0x55a7);
        quint8 eof = quint8(0xaa);
        sendStream << header;
        sendStream << eof;

        sendData.insert(2, data);


        emit sentBytes(sendData);

}
